﻿using System;
using System.Collections.Generic;
using RenRen.Schema;
using RenRen.Session;
using RenRen.Utility;
using System.Reflection;

namespace RenRen.Rest
{
	/// <summary>
	/// RenRen Connect接口
	/// </summary>
	public class Connect : RestBase
	{
		#region Methods

		#region Constructor

		/// <summary>
		/// 构造函数
		/// </summary>
		public Connect(RenRenSession session)
			: base(session)
		{
		}

		#endregion Constructor

		#region Public Methods


		#region Synchronous Methods

        /// <summary>
        /// 删除站点用户和校内用户之间的映射关系
        /// </summary>
        /// <param name="email_hashes">一个用户的email_hash值的数组</param>
        /// <returns></returns>
        public IList<string> UnregisterUsers(List<string> email_hashes)
		{
			return UnregisterUsers(email_hashes, false, null, null);
		}

		/// <summary>
        /// 用来建立站点用户和校内用户之间的映射关系
		/// </summary>
        /// <param name="accounts">代表用户账号信息的数组，最大长度为100。</param>
        /// <returns></returns>
		public string RegisterUsers(List<ConnectAccountMap> accounts)
		{
			return RegisterUsers(accounts, false, null, null);
		}
 
		
		#endregion


		#region Asynchronous Methods

        /// <summary>
        /// Unregisters a previously registered account (using connect.registerUsers). You should call this method if the user deletes his or her account on your site. (for RenRen Connect).
        /// </summary>
        /// <param name="email_hashes">An array of email_hashes to unregister.</param>
        /// <param name="callback">The AsyncCallback delegate</param>
        /// <param name="state">An object containing state information for this asynchronous request</param>        
        /// <returns>This method returns a List of unregistered email hashes. If any email hashes are missing, we recommend that you try unregistering the account again later.</returns>
        public void UnregisterUsersAsync(List<string> email_hashes, UnregisterUsersCallback callback, Object state)
		{
			UnregisterUsers(email_hashes, true, callback, state);
		}

        /// <summary>
        /// Creates an association between an existing user account on your site and that user's RenRen account, provided the user has not connected accounts before (for RenRen Connect).
        /// </summary>
        /// <param name="accounts">An array of up to 1,000 arrays, or "maps," where each map represent a connected account.</param>
        /// <param name="callback">The AsyncCallback delegate</param>
        /// <param name="state">An object containing state information for this asynchronous request</param>        
        /// <returns>This method returns a List email hashes that have been successfully registered. If any email hashes are missing, we recommend that you try registering them again later.</returns>
        public void RegisterUsersAsync(List<ConnectAccountMap> accounts, RegisterUsersCallback callback, Object state)
		{
			RegisterUsers(accounts, true, callback, state);
		}
 

		#endregion

		#endregion Public Methods
        
		#region Private Methods

		private IList<string> UnregisterUsers(List<string> email_hashes, bool isAsync, UnregisterUsersCallback callback, Object state)
		{
            //var parameterList = new Dictionary<string, string> { { "method", "renren.connect.unregisterUsers" } };
            //Utilities.AddRequiredParameter(parameterList, "email_hashes", JSONHelper.ConvertToJSONArray(email_hashes));

            //if (isAsync)
            //{
            //    SendRequestAsync<connect_unregisterUsers_response, IList<string>>(parameterList, !string.IsNullOrEmpty(Session.SessionKey), new RenRenCallCompleted<IList<string>>(callback), state);
            //    return null;
            //}
            //var response = SendRequest<connect_unregisterUsers_response>(parameterList,HasSession);
            //return response.connect_unregisterUsers_response_elt;

            return null;
		}

        private string RegisterUsers(ICollection<ConnectAccountMap> accountMaps, bool isAsync, RegisterUsersCallback callback, Object state)
        {
            var parameterList = new Dictionary<string, string> { { "method", "renren.connect.registerUsers" } };
            var itemList = new List<string>();
            
            foreach (var accountMap in accountMaps)
            {
                var mappingDictionary = new Dictionary<string, string>();

                // Compute the email_hash
                mappingDictionary.Add("email_hash", Utilities.GenerateEmailHash(accountMap.EmailAddress));

                // If populated set AccountId
                if (!string.IsNullOrEmpty(accountMap.AccountId))
                {
                    mappingDictionary.Add("account_id", accountMap.AccountId);
                }

                // If populated set AccountUrl
                if (!string.IsNullOrEmpty(accountMap.AccountUrl))
                {
                    mappingDictionary.Add("account_url", accountMap.AccountUrl);
                }
                
                itemList.Add(JSONHelper.ConvertToJSONAssociativeArray(mappingDictionary));
            }
            Utilities.AddRequiredParameter(parameterList, "accounts", JSONHelper.ConvertToJSONArray(itemList));

            if (isAsync)
            {
                SendRequestAsync<string, IList<string>>(parameterList,HasSession, new RenRenCallCompleted<IList<string>>(callback), state);
                return null;
            }

            var response = SendRequest<string>(parameterList,HasSession);
			return response;
        }

 

		#endregion Private Methods
        
		#endregion Methods

		#region Delegates

        /// <summary>
        /// Delegate called when UnregisterUsers call completed
        /// </summary>
        /// <param name="emailHashes">Hashes of the emails to unregister.</param>
        /// <param name="state">An object containing state information for this asynchronous request.</param>
        /// <param name="e">Exception object, if the call resulted in exception.</param>
		public delegate void UnregisterUsersCallback(IList<string> emailHashes, Object state, RenRenException e);

        /// <summary>
        /// Delegate called when RegisterUsers call completed
        /// </summary>
        /// <param name="emailHashes">Hases of the emails of the users to unregister.</param>
        /// <param name="state">An object containing state information for this asynchronous request.</param>
        /// <param name="e">Exception object, if the call resulted in exception.</param>
        public delegate void RegisterUsersCallback(IList<string> emailHashes, Object state, RenRenException e);

        /// <summary>
        /// Delegate called when GetUnconnectedFriends call completed
        /// </summary>
        /// <param name="numFriends">The count of unconnected friends.</param>
        /// <param name="state">An object containing state information for this asynchronous request.</param>
        /// <param name="e">Exception object, if the call resulted in exception.</param>
        public delegate void GetUnconnectedFriendsCallback(int numFriends, Object state, RenRenException e);

		#endregion Delegates
	}

    /// <summary>
    /// A helper object to store one RenRen Connect account map, where each map represents one RenRen Connect site email address and one of two
    /// optional Account identifiers.  This object is used to register third-party accounts with existing RenRen accounts.
    /// </summary>
    public class ConnectAccountMap
    {
        /// <summary>
        /// The email account of the remote (Connect site) account.
        /// </summary>
        public string EmailAddress { get; set; }

        /// <summary>
        /// Optional: The user's account ID on the RenRen Connect site. If you specify the AccountId property, then you must also set a 
        /// Connect Preview URL in your application's settings in order to generate a full user URL. The Connect Preview URL contains an 
        /// AccountId parameter, such as http://www.example.com/profile.php?user=AccountId. 
        /// </summary>
        public string AccountId { get; set; }

        /// <summary>
        /// Optional:  The URL to the user's account on the RenRen Connect site.  If you specify the AccountUrl property, that URL will be used directly.
        /// RenRen recommends that you specify at least one of either the AccountId or the AccountUrl properties.
        /// </summary>
        public string AccountUrl { get; set; }
    }
}